/**
 * @p.md
 * 
 * ActorContext 实现 Context 接口，为 Actor 提供运行时上下文
 */
import { Context, MessagePart, SenderPart, ReceiverPart, InfoPart, BasePart, SpawnerPart, StopperPart } from './context';
import { PID } from './pid';
import { Actor } from './actor';
import { ActorSystem } from './actorSystem';
import { Props } from './props';
import { Future } from './future';
import * as SystemMessages from './systemMessages';
import { ProcessRegistry } from './processRegistry';

/**
 * ActorContext 提供 Actor 运行时上下文，实现 Context 接口
 */
export class ActorContext implements Context {
  private _actor: Actor;
  private _self: PID;
  private _parent: PID | null;
  private _system: ActorSystem;
  private _currentMessage: any;
  private _currentSender?: PID;
  private _children: Set<PID> = new Set();
  private _receiveTimeout: number = 0;
  private _receiveTimeoutTimer?: NodeJS.Timeout;
  private _stash?: any[];

  /**
   * 构造函数
   * @param actor Actor 实例
   * @param self 当前 Actor 的 PID
   * @param parent 父 Actor 的 PID
   * @param system Actor 系统
   */
  constructor(actor: Actor, self: PID, parent: PID | null, system: ActorSystem) {
    this._actor = actor;
    this._self = self;
    this._parent = parent;
    this._system = system;
  }

  // InfoPart 接口实现
  
  /**
   * 获取父 Actor
   */
  parent(): PID | null {
    return this._parent;
  }

  /**
   * 获取当前 Actor 的 PID
   */
  self(): PID {
    return this._self;
  }

  /**
   * 获取当前 Actor 实例
   */
  actor(): Actor {
    return this._actor;
  }

  /**
   * 获取所属的 Actor 系统
   */
  actorSystem(): ActorSystem {
    return this._system;
  }

  // MessagePart 接口实现
  
  /**
   * 获取当前处理的消息
   */
  message(): any {
    return this._currentMessage;
  }

  // SenderPart 接口实现
  
  /**
   * 发送消息给指定的 Actor
   * @param target 目标 Actor 的 PID
   * @param message 要发送的消息
   */
  send(target: PID, message: any): void {
    const processRegistry = ProcessRegistry.getInstance();
    const process = processRegistry.get(target);
    if (process) {
      process.sendUserMessage(target, message);
    }
  }

  /**
   * 发送请求给指定的 Actor，期望得到响应
   * @param target 目标 Actor 的 PID
   * @param message 要发送的消息
   */
  request(target: PID, message: any): void {
    const envelope = {
      message,
      sender: this._self
    };
    this.send(target, envelope);
  }

  /**
   * 发送请求给指定的 Actor，并返回一个 Future 对象以获取响应
   * @param target 目标 Actor 的 PID
   * @param message 要发送的消息
   * @param timeout 超时时间（毫秒）
   */
  requestFuture(target: PID, message: any, timeout: number = 3000): Future<any> {
    return target.requestFuture(message, timeout, this._system);
  }

  // ReceiverPart 接口实现
  
  /**
   * 获取当前消息的发送者
   */
  sender(): PID | undefined {
    return this._currentSender;
  }

  // BasePart 接口实现
  
  /**
   * 获取当前接收超时设置
   */
  receiveTimeout(): number {
    return this._receiveTimeout;
  }

  /**
   * 获取当前 Actor 的子 Actor 列表
   */
  children(): PID[] {
    return Array.from(this._children);
  }

  /**
   * 回复当前消息的发送者
   * @param response 回复的消息
   */
  respond(response: any): void {
    if (!this._currentSender) {
      return;
    }
    
    this.send(this._currentSender, response);
  }

  /**
   * 将当前消息存入暂存区
   */
  stash(): void {
    if (!this._stash) {
      this._stash = [];
    }
    
    this._stash.push(this._currentMessage);
  }

  /**
   * 监视指定的 Actor
   * @param pid 要监视的 Actor 的 PID
   */
  watch(pid: PID): void {
    const message = new SystemMessages.Watch(this._self);
    this.sendSystemMessage(pid, message);
  }

  /**
   * 取消监视指定的 Actor
   * @param pid 要取消监视的 Actor 的 PID
   */
  unwatch(pid: PID): void {
    const message = new SystemMessages.Unwatch(this._self);
    this.sendSystemMessage(pid, message);
  }

  /**
   * 设置接收超时时间
   * @param duration 超时时间（毫秒），小于 1 毫秒将禁用超时
   */
  setReceiveTimeout(duration: number): void {
    this.cancelReceiveTimeout();
    
    if (duration <= 0) {
      this._receiveTimeout = 0;
      return;
    }
    
    this._receiveTimeout = duration;
    this._receiveTimeoutTimer = setTimeout(() => {
      const message = new SystemMessages.ReceiveTimeout();
      this.receiveMessage(message, undefined);
    }, duration);
  }

  /**
   * 取消接收超时设置
   */
  cancelReceiveTimeout(): void {
    if (this._receiveTimeoutTimer) {
      clearTimeout(this._receiveTimeoutTimer);
      this._receiveTimeoutTimer = undefined;
    }
  }

  /**
   * 将当前消息转发给指定的 Actor
   * @param pid 目标 Actor 的 PID
   */
  forward(pid: PID): void {
    const message = this._currentMessage;
    const sender = this._currentSender;
    
    if (sender) {
      const envelope = {
        message,
        sender
      };
      this.send(pid, envelope);
    } else {
      this.send(pid, message);
    }
  }

  /**
   * 在 Future 完成后重新进入 Actor 处理
   * @param future 等待的 Future
   * @param continuation 完成后的回调函数
   */
  reenterAfter(future: Future<any>, continuation: (result: any, error: Error | null) => void): void {
    future.result()
      .then(result => {
        // 当 Future 完成后，通过特殊消息重新进入 Actor 处理
        const message = new SystemMessages.Continuation(result, null, continuation);
        this.sendSystemMessage(this._self, message);
      })
      .catch(error => {
        const message = new SystemMessages.Continuation(null, error, continuation);
        this.sendSystemMessage(this._self, message);
      });
  }

  // SpawnerPart 接口实现
  
  /**
   * 创建一个新的 Actor
   * @param props Actor 属性
   */
  spawn(props: Props): PID {
    const processRegistry = ProcessRegistry.getInstance();
    const name = processRegistry.nextId();
    return this.spawnNamed(props, name);
  }

  /**
   * 创建一个指定名称的新 Actor
   * @param props Actor 属性
   * @param name 新 Actor 的名称
   */
  spawnNamed(props: Props, name: string): PID {
    const pid = props.spawn(this._system, name, this);
    this._children.add(pid);
    return pid;
  }

  /**
   * 创建一个带有前缀的新 Actor
   * @param props Actor 属性
   * @param prefix 名称前缀
   */
  spawnPrefix(props: Props, prefix: string): PID {
    const processRegistry = ProcessRegistry.getInstance();
    const name = `${prefix}${processRegistry.nextId()}`;
    return this.spawnNamed(props, name);
  }

  // StopperPart 接口实现
  
  /**
   * 停止指定的 Actor
   * @param pid 要停止的 Actor 的 PID
   */
  stop(pid: PID): void {
    if (this._children.has(pid)) {
      this._children.delete(pid);
    }
    
    pid.stop(this._system);
  }

  /**
   * 设置当前消息，用于内部处理
   * @param message 当前消息
   * @param sender 消息发送者
   */
  receiveMessage(message: any, sender?: PID): void {
    this._currentMessage = message;
    this._currentSender = sender;
    
    // 处理信封消息
    if (message && typeof message === 'object' && 'message' in message && 'sender' in message) {
      this._currentMessage = message.message;
      this._currentSender = message.sender;
    }
    
    try {
      this._actor.receive(this);
    } catch (error) {
      // 在实际实现中，这里应该通过监督系统处理错误
      console.error(`Error in actor ${this._self.toString()}:`, error);
    }
  }

  /**
   * 发送系统消息给指定目标
   * @param target 目标 PID
   * @param message 系统消息
   */
  private sendSystemMessage(target: PID, message: any): void {
    const process = this._system.processRegistry.get(target);
    if (process) {
      process.sendSystemMessage(target, message);
    }
  }
} 